package com.titaniume.java2;

/**
 *@program: JavaSenior
 *@description: 使用两个线程打印 1-100。线程1, 线程2 交替打印
 *
 *
 *
 * 涉及到的三个方法：
 *
 * wait():
 *  一旦执行此方法，当前线程进入阻塞状态，并释放同步监视器
 * notify():
 *  一旦执行此方法，就会唤醒wait的一个线程，如果有多个线程被wait就唤醒级别高的那个
 * notifyAll();
 *  一旦执行此方法，就会唤醒所有被wait的线程
 *
 * 说明：
 * 1.wait() notify(),notifyAll() 三个方法必须使用在同步代码块或同步方法中
 * 2.wait() notify(),notifyAll() 三个方法调用者必须是同步代码块或同步方法中的监视器
 * 否则出现 java.lang.IllegalMonitorStateException
 *
 *
 * 面试题: sleep() 和 wait() 的异同？
 *
 *  相同点： 一旦执行方法都可以使得当前线程进入阻塞状态
 *  不同点：
 *      1.两个方法声明的位置不同步 Thread中声明sleep(),Object声明wait()
 *      2.调用的要求不同: sleep() 可以在任何地方调用。wait()必须使用在同步代码块或同步方法中
 *      3.关于是否释放同步监视器： 如果两个方法都使用在同步代码块或同步方法中，sleep()方法不会释放锁（同步监视器），wait()会释放锁（同步监视器）
 *
 *
 *
 *@author: renfei.huang
 *@create: 2021-09-30 09:57
 */
public class CommunicationTest {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);
        t1.setName("线程1");
        t2.setName("线程2");
        t1.start();
        t2.start();
    }
}

class  Number implements  Runnable{

    private  int number = 1;

    private Object obj =  new Object();

    @Override
    public void run() {

        while (true){

            //this 唯一的Numbe对象
            //任何一个对象都可以充电同步监视器 这里也可以用this
            synchronized (obj) {

                //省略了this,Number的对象
                obj.notify();

                if(number <= 100){

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName()+":"+number);
                    number++;
                    try {
                        //使得调用如下wait()的线程进入阻塞状态
                        //省略了this,Number的对象
                       obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else {
                    break;
                }
            }

        }
    }
}